/** ****************************************************************************
@addtogroup TempLight
@{
*******************************************************************************/

#include "stdc.h"
#include "std_log.h"
#include "std_type.h"
#include "share/zyutils.h"

#include "color_light.h"
#include "share/color_space.h"

#define LOGTAG "COLOR_LIGHT"

void color_light_init(driver_color_light_t* dev, FUNC_GPIO_PwmSetDuty funcRedPwmSetDuty, FUNC_GPIO_PwmSetDuty funcGreenPwmSetDuty, FUNC_GPIO_PwmSetDuty funcBluePwmSetDuty) {
	dev->funcRedPwmSetDuty	= funcRedPwmSetDuty;
	dev->funcGreenPwmSetDuty= funcGreenPwmSetDuty;
	dev->funcBluePwmSetDuty	= funcBluePwmSetDuty;
	dev->hue = 0;
	dev->saturation = 0;
	dev->lightness = 0;
	dev->blinkTaskId = NULL;
	dev->blinkExOnTime = 0;
}

bool color_light_set_hue(driver_color_light_t* dev, uint16_t hue) {
	return color_light_set_hsl(dev, hue, dev->saturation, dev->lightness);
}

bool color_light_set_saturation(driver_color_light_t* dev, uint16_t saturation) {
	return color_light_set_hsl(dev, dev->hue, saturation, dev->lightness);
}

bool color_light_set_lightness(driver_color_light_t* dev, uint16_t lightness) {
	return color_light_set_hsl(dev, dev->hue, dev->saturation, lightness);
}

bool color_light_set_hsl(driver_color_light_t* dev, uint16_t hue, uint16_t saturation, uint16_t lightness) {
	uint8_t red, green, blue;
	HSL2RGB(hue*1.0/65535, saturation*1.0/65535, lightness*1.0/65535, &red, &green, &blue);
	return color_light_set_rgb(dev, red, green, blue);
}

bool color_light_set_rgb(driver_color_light_t* dev, uint8_t red, uint8_t green, uint8_t blue) {
	logd("Set light RGB: (%d, %d, %d)\r\n", red, green, blue);
	return true;
}

bool color_light_set_temperature(driver_color_light_t* dev, uint16_t temperature) {
	uint8_t red, green, blue;
	T2RGB(temperature, &red, &green, &blue);
	return color_light_set_rgb(dev, red, green, blue);
}

bool color_light_set_ctl(driver_color_light_t* dev, uint16_t temperature, uint16_t lightness) {
	return color_light_set_temperature(dev, temperature);
}

bool color_light_switchTo(driver_color_light_t* dev, switch_state_t state, uint32_t keepTime1, uint32_t keepTime2, uint8_t flashTimes) {
    // 如果之前已经调过 blinkEx() ，则取消之前的
    color_light_blinkStop(dev);

    if(state == SWITCH_OFF) {
        return color_light_off(dev);
    } else if(state == SWITCH_ON) {
        return color_light_on(dev);
    } else if(state == SWITCH_TOGGLE) {
        color_light_toggle(dev);
		return true;
    } else if(state == SWITCH_BLINK) {
        color_light_blinkEx(dev, keepTime1, keepTime2, flashTimes);
    }
    return false;
}

static void blinkHandler(uint8_t len, void* data) {
	driver_color_light_t* dev = (driver_color_light_t*)getPointer(data);
	color_light_off(dev);
}

void color_light_blink(driver_color_light_t* dev, uint16_t time) {
	color_light_on(dev);
	osTaskRunAfter(time, blinkHandler, sizeof(void*), &dev);
}

static void blinkExHandler(uint8_t len, void* data) {
	driver_color_light_t* dev = (driver_color_light_t*)getPointer(data);
	color_light_blink(dev, dev->blinkExOnTime);
}

uint16_t color_light_blinkEx(driver_color_light_t* dev, uint16_t onTime, uint16_t offTime, uint16_t count) {
	// 参数检查
	if(!(onTime && offTime && count>1)) { return NULL; }
    dev->blinkExOnTime = onTime;

    // 如果之前已经调过 blinkEx() ，则取消之前的
    osTaskDestroy(&dev->blinkTaskId);

    // 先闪第一次
    color_light_blink(dev, onTime);
    if(count != OSTASK_REPEAT_FOREVER) { count--; }

	// 安排后续的闪烁
	// 注意：需要把对象的指针传过去，以便在回调函数中访问对象
	return dev->blinkTaskId = osTaskRunEvery(onTime+offTime, count, blinkExHandler, sizeof(dev), &dev);
}


/// @}
